home *** CD-ROM | disk | FTP | other *** search
/ Isometric Game Programming with DirectX 7.0 / Isometric Game Programming.iso / source / chapter13 / isohex13_5 / isohex13_5.cpp < prev    next >
C/C++ Source or Header  |  2000-07-20  |  17KB  |  670 lines

  1. /*****************************************************************************
  2. IsoHex13_5.cpp
  3. Ernest S. Pazera
  4. 19JUL2000
  5. Start a WIN32 Application Workspace, add in this file
  6. Requires ddraw.lib and dxguid.lib
  7. Needs DDFuncs.h/cpp, GDICanvas.h/cpp, and TileSet.h/cpp
  8. *****************************************************************************/
  9.  
  10. //////////////////////////////////////////////////////////////////////////////
  11. //INCLUDES
  12. //////////////////////////////////////////////////////////////////////////////
  13. #define WIN32_LEAN_AND_MEAN  
  14.  
  15. #include <windows.h>   
  16. #include "TileSet.h"
  17.  
  18. //////////////////////////////////////////////////////////////////////////////
  19. //DEFINES
  20. //////////////////////////////////////////////////////////////////////////////
  21. //name for our window class
  22. #define WINDOWCLASS "ISOHEX13"
  23. //title of the application
  24. #define WINDOWTITLE "IsoHex 13-5"
  25.  
  26. //map dimensions
  27. const int MAPWIDTH=20;
  28. const int MAPHEIGHT=40;
  29.  
  30. enum IsoDirection{
  31. ISO_NORTH=0,
  32. ISO_NORTHEAST=1,
  33. ISO_EAST=2,
  34. ISO_SOUTHEAST=3,
  35. ISO_SOUTH=4,
  36. ISO_SOUTHWEST=5,
  37. ISO_WEST=6,
  38. ISO_NORTHWEST=7
  39. };
  40.  
  41. //mousemap directions
  42. enum MouseMapDirection{
  43.     MM_CENTER=0,
  44.     MM_NW=1,
  45.     MM_NE=2,
  46.     MM_SW=3,
  47.     MM_SE=4
  48. };
  49.  
  50. //mousemap structure
  51. struct CMouseMap
  52. {
  53.     POINT ptSize;
  54.     POINT ptRef;
  55.     MouseMapDirection* mmdLookUp;
  56. };
  57.  
  58. //////////////////////////////////////////////////////////////////////////////
  59. //PROTOTYPES
  60. //////////////////////////////////////////////////////////////////////////////
  61. bool Prog_Init();//game data initalizer
  62. void Prog_Loop();//main game loop
  63. void Prog_Done();//game clean up
  64. POINT StagMap_TilePlotter(POINT ptMap,int iTileWidth,int iTileHeight);
  65. POINT StagMap_TileWalker(POINT ptStart,IsoDirection Dir);
  66. POINT StagMap_MouseMapper(POINT ptMouse,CMouseMap* pmm);
  67. void SetUpSpaces();//sets up spaces
  68. void SetUpMap();
  69. void DrawMap();
  70. void ShowIsoCursor();
  71. void LoadMouseMap(CMouseMap* pmm,LPCTSTR lpszFileName);
  72. void ClipScreenAnchor();
  73.  
  74. //////////////////////////////////////////////////////////////////////////////
  75. //GLOBALS
  76. //////////////////////////////////////////////////////////////////////////////
  77. HINSTANCE hInstMain=NULL;//main application handle
  78. HWND hWndMain=NULL;//handle to our main window
  79. LPDIRECTDRAW7 lpdd=NULL;//directdraw
  80. LPDIRECTDRAWSURFACE7 lpddsMain=NULL;//primary surface
  81. LPDIRECTDRAWSURFACE7 lpddsBack=NULL;//back buffer
  82. LPDIRECTDRAWCLIPPER lpddClipper=NULL;//clipper
  83. CTileSet tsIso;//tileset
  84. CTileSet tsCursor;//cursor
  85. int iTileMap[MAPWIDTH][MAPHEIGHT];
  86. POINT ptCursor;//cursor position
  87.  
  88. //spaces
  89. RECT rcWorldSpace;//worldspace
  90. RECT rcScreenSpace;//screen space(also, view space)
  91. RECT rcAnchorSpace;//anchor space
  92. POINT ptScreenAnchor;//screen anchor
  93. POINT ptScreenAnchorScroll;//scrolling for the screen anchor
  94.  
  95. //mouse map
  96. CMouseMap mmMouseMap;
  97.  
  98.  
  99. //////////////////////////////////////////////////////////////////////////////
  100. //WINDOWPROC
  101. //////////////////////////////////////////////////////////////////////////////
  102. LRESULT CALLBACK TheWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
  103. {
  104.     //which message did we get?
  105.     switch(uMsg)
  106.     {
  107.     case WM_MOUSEMOVE:
  108.         {
  109.             //grab mouse coordinate
  110.             POINT ptMouse;
  111.             ptMouse.x=LOWORD(lParam);
  112.             ptMouse.y=HIWORD(lParam);
  113.             //mousemap the mouse coordinates
  114.             ptCursor=StagMap_MouseMapper(ptMouse,&mmMouseMap);
  115.  
  116.             //clip cursor to tilemap
  117.             if(ptCursor.x<0) ptCursor.x=0;
  118.             if(ptCursor.y<0) ptCursor.y=0;
  119.             //if(ptCursor.x>MAPWIDTH-1) ptCursor.x=MAPWIDTH-1;(eliminated)
  120.             if(ptCursor.y>MAPHEIGHT-1) ptCursor.y=MAPHEIGHT-1;
  121.  
  122.             //check for scrolling zones
  123.             ptScreenAnchorScroll.x=0;
  124.             ptScreenAnchorScroll.y=0;
  125.             //top
  126.             if(ptMouse.y<8)
  127.             {
  128.                 ptScreenAnchorScroll.y=-(8-ptMouse.y);
  129.             }
  130.             //bottom
  131.             if(ptMouse.y>472)
  132.             {
  133.                 ptScreenAnchorScroll.y=(ptMouse.y-472);
  134.             }
  135.             //left
  136.             if(ptMouse.x<8)
  137.             {
  138.                 ptScreenAnchorScroll.x=-(8-ptMouse.x);
  139.             }
  140.             //right
  141.             if(ptMouse.x>632)
  142.             {
  143.                 ptScreenAnchorScroll.x=(ptMouse.x-632);
  144.             }
  145.  
  146.             return(0);
  147.         }break;
  148.     case WM_KEYDOWN:
  149.         {
  150.             //if escape hit, destroy window
  151.             if(wParam==VK_ESCAPE) DestroyWindow(hWndMain);
  152.             //handled, so return 0
  153.             return(0);
  154.         }break;
  155.     case WM_DESTROY://the window is being destroyed
  156.         {
  157.  
  158.             //tell the application we are quitting
  159.             PostQuitMessage(0);
  160.  
  161.             //handled message, so return 0
  162.             return(0);
  163.  
  164.         }break;
  165.     case WM_PAINT://the window needs repainting
  166.         {
  167.             //a variable needed for painting information
  168.             PAINTSTRUCT ps;
  169.             
  170.             //start painting
  171.             HDC hdc=BeginPaint(hwnd,&ps);
  172.  
  173.             /////////////////////////////
  174.             //painting code would go here
  175.             /////////////////////////////
  176.  
  177.             //end painting
  178.             EndPaint(hwnd,&ps);
  179.                         
  180.             //handled message, so return 0
  181.             return(0);
  182.         }break;
  183.     }
  184.  
  185.     //pass along any other message to default message handler
  186.     return(DefWindowProc(hwnd,uMsg,wParam,lParam));
  187. }
  188.  
  189.  
  190. //////////////////////////////////////////////////////////////////////////////
  191. //WINMAIN
  192. //////////////////////////////////////////////////////////////////////////////
  193. int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd)
  194. {
  195.     //assign instance to global variable
  196.     hInstMain=hInstance;
  197.  
  198.     //create window class
  199.     WNDCLASSEX wcx;
  200.  
  201.     //set the size of the structure
  202.     wcx.cbSize=sizeof(WNDCLASSEX);
  203.  
  204.     //class style
  205.     wcx.style=CS_OWNDC | CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
  206.  
  207.     //window procedure
  208.     wcx.lpfnWndProc=TheWindowProc;
  209.  
  210.     //class extra
  211.     wcx.cbClsExtra=0;
  212.  
  213.     //window extra
  214.     wcx.cbWndExtra=0;
  215.  
  216.     //application handle
  217.     wcx.hInstance=hInstMain;
  218.  
  219.     //icon
  220.     wcx.hIcon=LoadIcon(NULL,IDI_APPLICATION);
  221.  
  222.     //cursor
  223.     wcx.hCursor=LoadCursor(NULL,IDC_ARROW);
  224.  
  225.     //background color
  226.     wcx.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
  227.  
  228.     //menu
  229.     wcx.lpszMenuName=NULL;
  230.  
  231.     //class name
  232.     wcx.lpszClassName=WINDOWCLASS;
  233.  
  234.     //small icon
  235.     wcx.hIconSm=NULL;
  236.  
  237.     //register the window class, return 0 if not successful
  238.     if(!RegisterClassEx(&wcx)) return(0);
  239.  
  240.     //create main window
  241.     hWndMain=CreateWindowEx(0,WINDOWCLASS,WINDOWTITLE, WS_POPUP | WS_VISIBLE,0,0,320,240,NULL,NULL,hInstMain,NULL);
  242.  
  243.     //error check
  244.     if(!hWndMain) return(0);
  245.  
  246.     //if program initialization failed, then return with 0
  247.     if(!Prog_Init()) return(0);
  248.  
  249.     //message structure
  250.     MSG msg;
  251.  
  252.     //message pump
  253.     for(;;)    
  254.     {
  255.         //look for a message
  256.         if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
  257.         {
  258.             //there is a message
  259.  
  260.             //check that we arent quitting
  261.             if(msg.message==WM_QUIT) break;
  262.             
  263.             //translate message
  264.             TranslateMessage(&msg);
  265.  
  266.             //dispatch message
  267.             DispatchMessage(&msg);
  268.         }
  269.  
  270.         //run main game loop
  271.         Prog_Loop();
  272.     }
  273.     
  274.     //clean up program data
  275.     Prog_Done();
  276.  
  277.     //return the wparam from the WM_QUIT message
  278.     return(msg.wParam);
  279. }
  280.  
  281. //////////////////////////////////////////////////////////////////////////////
  282. //INITIALIZATION
  283. //////////////////////////////////////////////////////////////////////////////
  284. bool Prog_Init()
  285. {
  286.     //set up ddraw
  287.     lpdd=LPDD_Create(hWndMain,DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT);
  288.     lpdd->SetDisplayMode(640,480,16,0,0);
  289.  
  290.     //set up primary surface
  291.     lpddsMain=LPDDS_CreatePrimary(lpdd,1);
  292.  
  293.     //set up back buffer
  294.     lpddsBack=LPDDS_GetSecondary(lpddsMain);
  295.  
  296.     //create clipper
  297.     lpdd->CreateClipper(0,&lpddClipper,NULL);
  298.     lpddClipper->SetHWnd(0,hWndMain);
  299.     lpddsBack->SetClipper(lpddClipper);
  300.  
  301.     //load in tileset
  302.     tsIso.Load(lpdd,"IsoHex13_5-1.bmp");
  303.     tsCursor.Load(lpdd,"IsoHex13_5-2.bmp");
  304.     //load in mousemap
  305.     LoadMouseMap(&mmMouseMap,"IsoHex13_5-3.bmp");
  306.     //set up mousemap reference point
  307.     POINT ptMap;
  308.     ptMap.x=0;
  309.     ptMap.y=0;
  310.     mmMouseMap.ptRef=StagMap_TilePlotter(ptMap,mmMouseMap.ptSize.x,mmMouseMap.ptSize.y);
  311.     mmMouseMap.ptRef.x+=tsIso.GetTileList()[0].rcDstExt.left;
  312.     mmMouseMap.ptRef.y+=tsIso.GetTileList()[0].rcDstExt.top;
  313.  
  314.     //set up spaces
  315.     SetUpSpaces();
  316.  
  317.     //set up the tilemap
  318.     SetUpMap();
  319.  
  320.     return(true);//return success
  321. }
  322.  
  323. //////////////////////////////////////////////////////////////////////////////
  324. //CLEANUP
  325. //////////////////////////////////////////////////////////////////////////////
  326. void Prog_Done()
  327. {
  328.     //deallocate lookup table for mousemap
  329.     delete [] mmMouseMap.mmdLookUp;
  330.     //clean up clipper
  331.     LPDDCLIP_Release(&lpddClipper);
  332.     //clean up primary surface
  333.     LPDDS_Release(&lpddsMain);
  334.     //clean up ddraw
  335.     LPDD_Release(&lpdd);
  336. }
  337.  
  338. //////////////////////////////////////////////////////////////////////////////
  339. //MAIN GAME LOOP
  340. //////////////////////////////////////////////////////////////////////////////
  341. void Prog_Loop()
  342. {
  343.     //clear out back buffer
  344.     DDBLTFX ddbltfx;
  345.     DDBLTFX_ColorFill(&ddbltfx,0);
  346.     lpddsBack->Blt(NULL,NULL,NULL,DDBLT_WAIT | DDBLT_COLORFILL,&ddbltfx);
  347.  
  348.     //scroll the map
  349.     ptScreenAnchor.x+=ptScreenAnchorScroll.x;
  350.     ptScreenAnchor.y+=ptScreenAnchorScroll.y;
  351.     ClipScreenAnchor();
  352.  
  353.     //show the board
  354.     DrawMap();
  355.  
  356.     //show the cursor
  357.     ShowIsoCursor();
  358.  
  359.     //flip
  360.     lpddsMain->Flip(NULL,DDFLIP_WAIT);
  361. }
  362.  
  363. POINT StagMap_TilePlotter(POINT ptMap,int iTileWidth,int iTileHeight)
  364. {
  365.     POINT ptReturn;
  366.     //calculate pixel position for the map position given
  367.     ptReturn.x=ptMap.x*iTileWidth+(ptMap.y & 1)*iTileWidth/2;
  368.     ptReturn.y=ptMap.y*iTileHeight/2;
  369.     //return calculate point
  370.     return(ptReturn);
  371. }
  372.  
  373. void SetUpMap()
  374. {
  375.     //randomly set up the map
  376.     for(int x=0;x<MAPWIDTH;x++)
  377.     {
  378.         for(int y=0;y<MAPHEIGHT;y++)
  379.         {
  380.             iTileMap[x][y]=rand()%(tsIso.GetTileCount());
  381.         }
  382.     }
  383. }
  384.  
  385. void DrawMap()
  386. {
  387.     POINT ptTile;//tile pixel coordinate
  388.     POINT ptMap;//map coordinate
  389.     //the y loop is outside, because we must blit in horizontal rows
  390.     for(int y=0;y<MAPHEIGHT;y++)
  391.     {
  392.         for(int x=0;x<MAPWIDTH*2;x++)
  393.         {
  394.             //get pixel coordinate for map position
  395.             ptMap.x=x;
  396.             ptMap.y=y;
  397.             ptTile=StagMap_TilePlotter(ptMap,mmMouseMap.ptSize.x,mmMouseMap.ptSize.y);
  398.             //plot the tile(adjust for anchor)
  399.             tsIso.PutTile(lpddsBack,ptTile.x-ptScreenAnchor.x,ptTile.y-ptScreenAnchor.y,iTileMap[x%MAPWIDTH][y]);
  400.         }
  401.     }
  402. }
  403.  
  404. void SetUpSpaces()
  405. {
  406.     //set up screen space
  407.     SetRect(&rcScreenSpace,0,0,640,480);
  408.     
  409.     //grab tile rectangle from tileset
  410.     RECT rcTile1;
  411.     RECT rcTile2;
  412.     POINT ptPlot;
  413.     POINT ptMap;
  414.  
  415.     //grab tiles from extents
  416.     CopyRect(&rcTile1,&tsIso.GetTileList()[0].rcDstExt);
  417.     CopyRect(&rcTile2,&tsIso.GetTileList()[0].rcDstExt);
  418.  
  419.     //move first tile to upper left position
  420.     ptMap.x=0;
  421.     ptMap.y=0;
  422.     ptPlot=StagMap_TilePlotter(ptMap,mmMouseMap.ptSize.x,mmMouseMap.ptSize.y);
  423.     OffsetRect(&rcTile1,ptPlot.x,ptPlot.y);
  424.  
  425.     //move first tile to lower right position
  426.     ptMap.x=MAPWIDTH-1;
  427.     ptMap.y=MAPHEIGHT-1;
  428.     ptPlot=StagMap_TilePlotter(ptMap,mmMouseMap.ptSize.x,mmMouseMap.ptSize.y);
  429.     OffsetRect(&rcTile2,ptPlot.x,ptPlot.y);
  430.  
  431.     //combine these two tiles into world space
  432.     UnionRect(&rcWorldSpace,&rcTile1,&rcTile2);
  433.  
  434.     //copy worldspace to anchor space
  435.     CopyRect(&rcAnchorSpace,&rcWorldSpace);
  436.  
  437.     //subtract out screenspace
  438.     //adjust right edge(removed)
  439.     //make sure right not less than left
  440.     if(rcAnchorSpace.right<rcAnchorSpace.left) rcAnchorSpace.right=rcAnchorSpace.left;
  441.     //adjust bottom edge
  442.     rcAnchorSpace.bottom-=(rcScreenSpace.bottom-rcScreenSpace.top);
  443.     //make sure bottom not less than top
  444.     if(rcAnchorSpace.bottom<rcAnchorSpace.top) rcAnchorSpace.bottom=rcAnchorSpace.top;
  445.  
  446.     //adjust edges of anchorspace for "no jaggies"
  447.     //add 1/2 height to top
  448.     rcAnchorSpace.top+=(mmMouseMap.ptSize.y/2);
  449.     //subtract 1/2 height from bottom
  450.     rcAnchorSpace.bottom-=(mmMouseMap.ptSize.y/2);
  451.     //add 1/2 width to left
  452.     rcAnchorSpace.left+=(mmMouseMap.ptSize.x/2);
  453.     //add 1/2 width from right(changed from 13_4
  454.     //rcAnchorSpace.right+=(mmMouseMap.ptSize.x/2);
  455.  
  456.     //initialize screen anchor
  457.     ptScreenAnchor.x=rcAnchorSpace.left;
  458.     ptScreenAnchor.y=rcAnchorSpace.top;
  459.  
  460.     //initialize cursor
  461.     ptCursor.x=0;
  462.     ptCursor.y=0;
  463. }
  464.  
  465. POINT StagMap_TileWalker(POINT ptStart, IsoDirection Dir)
  466. {
  467.     //depending on direction, move the point
  468.     switch(Dir)
  469.     {
  470.     case ISO_NORTH:
  471.         {
  472.             ptStart.y-=2;
  473.         }break;
  474.     case ISO_NORTHEAST:
  475.         {
  476.             ptStart.x+=(ptStart.y&1);
  477.             ptStart.y--;
  478.         }break;
  479.     case ISO_EAST:
  480.         {
  481.             ptStart.x++;
  482.         }break;
  483.     case ISO_SOUTHEAST:
  484.         {
  485.             ptStart.x+=(ptStart.y&1);
  486.             ptStart.y++;
  487.         }break;
  488.     case ISO_SOUTH:
  489.         {
  490.             ptStart.y+=2;
  491.         }break;
  492.     case ISO_SOUTHWEST:
  493.         {
  494.             ptStart.x+=((ptStart.y&1)-1);
  495.             ptStart.y++;
  496.         }break;
  497.     case ISO_WEST:
  498.         {
  499.             ptStart.x--;
  500.         }break;
  501.     case ISO_NORTHWEST:
  502.         {
  503.             ptStart.x+=((ptStart.y&1)-1);
  504.             ptStart.y--;
  505.         }break;
  506.     }
  507.     //return the point
  508.     return(ptStart);
  509. }
  510.  
  511. void ShowIsoCursor()
  512. {
  513.     //copy cursor position
  514.     POINT ptMap=ptCursor;
  515.  
  516.     //plot cursor position
  517.     POINT ptPlot=StagMap_TilePlotter(ptMap,mmMouseMap.ptSize.x,mmMouseMap.ptSize.y);
  518.     
  519.     //put the cursor image
  520.     tsCursor.PutTile(lpddsBack,ptPlot.x-ptScreenAnchor.x,ptPlot.y-ptScreenAnchor.y,0);
  521. }
  522.  
  523. void LoadMouseMap(CMouseMap* pmm,LPCTSTR lpszfilename)
  524. {
  525.     //create canvas
  526.     CGDICanvas gdic;
  527.     //load file
  528.     gdic.Load(NULL,lpszfilename);
  529.     //assign width/height
  530.     pmm->ptSize.x=gdic.GetWidth();
  531.     pmm->ptSize.y=gdic.GetHeight();
  532.     //allocate space for the lookup table
  533.     pmm->mmdLookUp= new
  534.         MouseMapDirection[gdic.GetWidth()*gdic.GetHeight()];
  535.     //colorref values for filling lookup
  536.     COLORREF crNW=GetPixel(gdic,0,0);
  537.     COLORREF crNE=GetPixel(gdic,gdic.GetWidth()-1,0);
  538.     COLORREF crSW=GetPixel(gdic,0,gdic.GetHeight()-1);
  539.     COLORREF crSE=GetPixel(gdic,gdic.GetWidth()-1, gdic.GetHeight()-1);
  540.     //test pixel color
  541.     COLORREF crTest;
  542.     //scan convert bitmap into lookup values
  543.     for(int y=0;y<gdic.GetHeight();y++)
  544.     {
  545.         for(int x=0;x<gdic.GetWidth();x++)
  546.         {
  547.             //grab test pixel
  548.             crTest=GetPixel(gdic,x,y);
  549.             //set lookup to default
  550.             pmm->mmdLookUp[x+y*pmm->ptSize.x]=MM_CENTER;
  551.             //check colors
  552.             if(crTest==crNW)
  553.                 pmm->mmdLookUp[x+y*pmm->ptSize.x]=MM_NW;
  554.             if(crTest==crNE)
  555.                 pmm->mmdLookUp[x+y*pmm->ptSize.x]=MM_NE;
  556.             if(crTest==crSW)
  557.                 pmm->mmdLookUp[x+y*pmm->ptSize.x]=MM_SW;
  558.             if(crTest==crSE)
  559.                 pmm->mmdLookUp[x+y*pmm->ptSize.x]=MM_SE;
  560.         }
  561.     }
  562. }
  563.  
  564. void ClipScreenAnchor()
  565. {
  566.     //wrap to left
  567.     if(ptScreenAnchor.x<rcAnchorSpace.left) ptScreenAnchor.x+=(rcAnchorSpace.right-rcAnchorSpace.left);
  568.     //clip to top
  569.     if(ptScreenAnchor.y<rcAnchorSpace.top) ptScreenAnchor.y=rcAnchorSpace.top;
  570.     //wrap to right
  571.     if(ptScreenAnchor.x>=rcAnchorSpace.right) ptScreenAnchor.x-=(rcAnchorSpace.right-rcAnchorSpace.left);;
  572.     //clip to bottom
  573.     if(ptScreenAnchor.y>=rcAnchorSpace.bottom) ptScreenAnchor.y=rcAnchorSpace.bottom-1;
  574. }
  575.  
  576. POINT StagMap_MouseMapper(POINT ptMouse,CMouseMap* pmm)
  577. {
  578.     //step1:screen to world
  579.     ptMouse.x+=ptScreenAnchor.x;
  580.     ptMouse.y+=ptScreenAnchor.y;
  581.  
  582.     //step2:relative world coordinates
  583.     ptMouse.x-=pmm->ptRef.x;
  584.     ptMouse.y-=pmm->ptRef.y;
  585.  
  586.     //step3:mousemap coords
  587.     POINT ptMouseMapCoarse;
  588.     POINT ptMouseMapFine;
  589.     //coarse mousemap coords
  590.     ptMouseMapCoarse.x=ptMouse.x/pmm->ptSize.x;
  591.     ptMouseMapCoarse.y=ptMouse.y/pmm->ptSize.y;
  592.     //fine mousemap coords
  593.     ptMouseMapFine.x=ptMouse.x%pmm->ptSize.x;
  594.     ptMouseMapFine.y=ptMouse.y%pmm->ptSize.y;
  595.     //adjust for negative fine coordinates
  596.     if(ptMouseMapFine.x<0)
  597.     {
  598.         ptMouseMapFine.x+=pmm->ptSize.x;
  599.         ptMouseMapCoarse.x--;
  600.     }
  601.     if(ptMouseMapFine.y<0)
  602.     {
  603.         ptMouseMapFine.y+=pmm->ptSize.y;
  604.         ptMouseMapCoarse.y--;
  605.     }
  606.  
  607.     //step4:coarse tilewalk
  608.     POINT ptMap;
  609.     ptMap.x=0;
  610.     ptMap.y=0;
  611.     //move north
  612.     while(ptMouseMapCoarse.y<0)
  613.     {
  614.         ptMouseMapCoarse.y++;
  615.         ptMap=StagMap_TileWalker(ptMap,ISO_NORTH);
  616.     }
  617.     //move south
  618.     while(ptMouseMapCoarse.y>0)
  619.     {
  620.         ptMouseMapCoarse.y--;
  621.         ptMap=StagMap_TileWalker(ptMap,ISO_SOUTH);
  622.     }
  623.     //move east
  624.     while(ptMouseMapCoarse.x>0)
  625.     {
  626.         ptMouseMapCoarse.x--;
  627.         ptMap=StagMap_TileWalker(ptMap,ISO_EAST);
  628.     }
  629.     //move west
  630.     while(ptMouseMapCoarse.x<0)
  631.     {
  632.         ptMouseMapCoarse.x++;
  633.         ptMap=StagMap_TileWalker(ptMap,ISO_WEST);
  634.     }
  635.  
  636.     //step5:fine tilewalk
  637.     //get lookup value
  638.     MouseMapDirection mmd=pmm->mmdLookUp[ptMouseMapFine.x+ptMouseMapFine.y*pmm->ptSize.x];
  639.     switch(mmd)
  640.     {
  641.     case MM_CENTER:
  642.         {
  643.             //do nothing
  644.         }break;
  645.     case MM_NW:
  646.         {
  647.             //move northwest
  648.             ptMap=StagMap_TileWalker(ptMap,ISO_NORTHWEST);
  649.         }break;
  650.     case MM_NE:
  651.         {
  652.             //move northeast
  653.             ptMap=StagMap_TileWalker(ptMap,ISO_NORTHEAST);
  654.         }break;
  655.     case MM_SW:
  656.         {
  657.             //move southwest
  658.             ptMap=StagMap_TileWalker(ptMap,ISO_SOUTHWEST);
  659.         }break;
  660.     case MM_SE:
  661.         {
  662.             //move southeast
  663.             ptMap=StagMap_TileWalker(ptMap,ISO_SOUTHEAST);
  664.         }break;
  665.     }
  666.  
  667.     //return map coordinate
  668.     return(ptMap);
  669. }
  670.